﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Text;
using System.Threading.Tasks;

/// <summary>
/// 统一在 GpFx 中修改
/// </summary>
namespace Common
{

    public class DataTableHelper
    {
        #region 参数
        public class Para_MergeDataTable
        {
            /// <summary>
            /// 目标数据表
            /// </summary>
            public DataTable Dt_Tar { get; set; }

            /// <summary>
            /// 源数据表
            /// </summary>
            public DataTable Dt_Ori { get; set; }

            /// <summary>
            /// 待赋值字段名称
            /// </summary>
            public List<string> ValueField { get; set; } = new List<string>();

            /// <summary>
            /// 联结字段。如果是主键，必须与源数据表主键顺序一致；目标表数据列名称在前，源数据表名称在后
            /// </summary>
            public Dictionary<string, string> JoinField { get; set; } = new Dictionary<string, string>();

            /// <summary>
            /// 源数据表中，联结字段是否是主键
            /// </summary>
            public bool IsPrimaryKey { get; set; }
        }

        public class Para_LimitValue
        {
            public string FieldName { get; set; }
            public Nullable<decimal> MinValue { get; set; }
            public Nullable<decimal> MaxValue { get; set; }
        }
        #endregion
        
        #region 合并表格
        public void MergeDataTable(Para_MergeDataTable objPara)
        {
            //建立表头Begin
            foreach (string fieldName in objPara.ValueField)
            {
                objPara.Dt_Tar.Columns.Add(fieldName, objPara.Dt_Ori.Columns[fieldName].DataType);
            }
            //建立表头End

            switch (objPara.JoinField.Count)
            {
                case 1:
                    if (objPara.IsPrimaryKey == true)
                    {
                        OneKey(objPara);
                        return;
                    }
                    else
                    {
                        OneJoinFiele(objPara);
                        return;
                    }
                case 2:
                    if (objPara.IsPrimaryKey == true)
                    {
                        TwoKey(objPara);
                        return;
                    }
                    else
                    {
                        TwoJoinFiele(objPara);
                        return;
                    }
                default:
                    break;
            }

        }

        private void OneKey(Para_MergeDataTable objPara)
        {
            DataRow row_Ori = objPara.Dt_Ori.NewRow();
            foreach (DataRow row_Tar in objPara.Dt_Tar.Rows)
            {
                row_Ori = objPara.Dt_Ori.NewRow();
                row_Ori = objPara.Dt_Ori.Rows.Find(row_Tar[objPara.JoinField.Keys.First()]);

                if (row_Ori != null)
                {
                    foreach (string fieldName in objPara.ValueField)
                    {
                        row_Tar[fieldName] = row_Ori[fieldName];
                    }
                }
            }
        }
        private void OneJoinFiele(Para_MergeDataTable objPara)
        {
            DataRow row_Ori = objPara.Dt_Ori.NewRow();
            string strFilter = "";
            foreach (DataRow row_Tar in objPara.Dt_Tar.Rows)
            {
                row_Ori = objPara.Dt_Ori.NewRow();

                strFilter = $"{objPara.JoinField.Values.First()} = '{row_Tar[objPara.JoinField.Keys.First()]}'";
                row_Ori = objPara.Dt_Ori.Select(strFilter).FirstOrDefault();

                if (row_Ori != null)
                {
                    foreach (string fieldName in objPara.ValueField)
                    {
                        row_Tar[fieldName] = row_Ori[fieldName];
                    }
                }
            }
        }
        private void TwoKey(Para_MergeDataTable objPara)
        {
            DataRow row_Ori = objPara.Dt_Ori.NewRow();
            foreach (DataRow row_Tar in objPara.Dt_Tar.Rows)
            {
                row_Ori = objPara.Dt_Ori.NewRow();
                row_Ori = objPara.Dt_Ori.Rows.Find(new object[] { row_Tar[objPara.JoinField.Keys.First()], row_Tar[objPara.JoinField.Keys.Last()] });

                if (row_Ori != null)
                {
                    foreach (string fieldName in objPara.ValueField)
                    {
                        row_Tar[fieldName] = row_Ori[fieldName];
                    }
                }
            }
        }
        private void TwoJoinFiele(Para_MergeDataTable objPara)
        {
            DataRow row_Ori = objPara.Dt_Ori.NewRow();
            string strFilter = "";
            foreach (DataRow row_Tar in objPara.Dt_Tar.Rows)
            {
                row_Ori = objPara.Dt_Ori.NewRow();

                strFilter = $"{objPara.JoinField.Values.First()} = '{row_Tar[objPara.JoinField.Keys.First()]}' " +
                    $"and {objPara.JoinField.Values.Last()} = '{row_Tar[objPara.JoinField.Keys.Last()]}' ";
                row_Ori = objPara.Dt_Ori.Select(strFilter).FirstOrDefault();

                if (row_Ori != null)
                {
                    foreach (string fieldName in objPara.ValueField)
                    {
                        row_Tar[fieldName] = row_Ori[fieldName];
                    }
                }
            }
        }
        #endregion

        #region 拆分表格
        public DataSet SplitDataTableByCount(DataTable ori_dt, int splitCount, bool isDesc = false)
        {
            DataSet dsResult = new DataSet();
            DataTable dtResult = new DataTable();
            DataTable tar_dt = ori_dt.Select ().CopyToDataTable ();

            string columnName = "RowId";
            int n;

            if (tar_dt.Columns.Contains(columnName) == false)
            {
                tar_dt.Columns.Add(columnName, typeof(int));
            }

            if (isDesc == false)
            {
                n = 0;
                foreach (DataRow itemRow in tar_dt.Rows)
                {
                    n++;
                    itemRow[columnName] = n;
                }
            }
            else
            {
                n = tar_dt.Rows.Count;
                foreach (DataRow itemRow in tar_dt.Rows)
                {
                    itemRow[columnName] = n;
                    n--;
                }
            }

            int row_Begin = 1;
            int row_End = 0;
            int row_Max = tar_dt.Rows.Count;
            do
            {
                row_End = row_End + splitCount;
                dtResult = new DataTable();
                dtResult = tar_dt.Select($"{columnName } >= {row_Begin} and {columnName } <= {row_End } ").CopyToDataTable();

                if (isDesc == true)
                {
                    dtResult.TableName = $"DescRow{row_Begin.ToString()}To{row_End.ToString()}";
                }
                else
                {
                    dtResult.TableName = $"AscRow{row_Begin.ToString()}To{row_End.ToString()}";
                }
                dsResult.Tables.Add(dtResult);

                row_Begin = row_Begin + splitCount;
            } while (row_End < row_Max);

            return dsResult;
        }
        #endregion

        #region 设置数据列极限值
        public DataTable SetLimitValue(DataTable dtOri, List<Para_LimitValue> para_LimitValueList)
        {
            DataTable dtResult = dtOri.Select().CopyToDataTable();
            

            foreach (DataRow itemRow in dtResult.Rows)
            {
                foreach (Para_LimitValue itemPara in para_LimitValueList)
                {
                    try
                    {
                        if ((decimal?)itemRow[itemPara.FieldName] < itemPara.MinValue)
                        {
                            itemRow[itemPara.FieldName] = itemPara.MinValue;
                        }
                    }
                    catch (Exception)
                    {
                    }
                    try
                    {
                        if ((decimal?)itemRow[itemPara.FieldName] > itemPara.MaxValue)
                        {
                            itemRow[itemPara.FieldName] = itemPara.MaxValue;
                        }
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            return dtResult;
        }

        #endregion

        #region 处理列
        public DataTable SortColumn(DataTable dtOri, List<string> orderName)
        {
            DataTable dtResult = dtOri.Copy();

            int i = 0;
            foreach (string item in orderName)
            {
                if (dtResult.Columns.Contains(item))
                {
                    dtResult.Columns[item].SetOrdinal(i);
                    i++;
                }
            }

            return dtResult;
        }
        public DataTable SelectColumn(DataTable dtOri, List<string> columnName)
        {
            DataTable dtResult = dtOri.Copy();
            List<string> columnList_Ori = new List<string>();
            List<string> delColumeList = new List<string>();

            foreach (DataColumn item in dtResult.Columns)
            {
                columnList_Ori.Add(item.ColumnName);
            }
            delColumeList = columnList_Ori.Except(columnName).ToList();

            foreach (string item in delColumeList )
            {
                if (dtResult .Columns .Contains (item ))
                {
                    dtResult.Columns.Remove(item);
                }
            }
            dtResult = SortColumn(dtResult, columnName);

            return dtResult;
        }
        #endregion
    }
}
